using System;
using System.Collections;
using SMS.SMPPClient.Util;

namespace SMS.SMPPClient.PDU.Outgoing
{
    /// <summary>
    /// Defines a submit_multi PDU.
    /// </summary>
    public class SMPPSubmitMulti : MessageLCD2
    {
        //note that all of the optional parameters are in the base class.

        private byte _NumberOfDests;
        private DestinationAddress[] _DestAddresses;

        private const int MAX_DESTS = 254;

        /// <summary>
        /// Creates a submit_multi PDU.
        /// </summary>
        /// <param name="serviceType">Indicates the SMS Application service associated with
        /// the message.</param>
        /// <param name="sourceAddrTON">Type of Number for source address.</param>
        /// <param name="sourceAddrNPI">Numbering Plan Indicator for source address.</param>
        /// <param name="sourceAddress">Address of SME which originated  this message.  If
        /// not known, set to null.</param>
        /// <param name="numberOfDests">Number of destination addresses - indicates the
        /// number of dest_address structures that are to follow.  A maximum of 254
        /// destination addresses are allowed.  Note: Set to 1 when submitting to one SME
        /// Address OR when submitting to one Distribution List.</param>
        /// <param name="destinationAddresses">Contains one or more (number_of_dests) SME
        /// addresses or/and Distribution List names.  Use the DestAddrFactory class to
        /// generate these.</param>
        /// <param name="esmClass">Indicates Message Mode and Message Type.  See the SMSC
        /// version 3.4 specification for details on setting this.  For most uses, you can
        /// set this to 0 (default SMSC actions).</param>
        /// <param name="protocolID">Protocol Identifier; Network specific field.</param>
        /// <param name="priorityFlag">The priority level of the message.</param>
        /// <param name="scheduleDeliveryTime">Scheduled delivery time for the message
        /// delivery.  Set to null for immediate delivery.  Otherwise, use YYMMDDhhmmsstnn
        /// as the format.  See section 7.1.1 of the SMPP spec for more details.</param>
        /// <param name="validityPeriod">The validity period of this message.  Set to null
        /// to request the SMSC default validity period.  Otherwise, use YYMMDDhhmmsstnn
        /// as the format.  See section 7.1.1 of the SMPP spec for more details.</param>
        /// <param name="registeredDelivery">Indicator to signify if an SMSC delivery
        /// receipt or an SME acknowledgment is required.</param>
        /// <param name="replaceIfPresentFlag">Indicates if the submitted message should
        /// replace an existing message.</param>
        /// <param name="smDefaultMsgID">The number of the canned SMSC message to use. If
        /// not using an SMSC canned message, set to 0.</param>
        /// <param name="dataCoding">The encoding scheme of the short message user data.
        /// </param>
        /// <param name="shortMessage">The short message to send, up to 160
        /// octets.  If you need more length, use the MessagePayload
        /// property.  Do not use both at the same time!  Setting this to
        /// null will result in an empty string.  This can be either a string or a
        /// byte array; anything else will result in an exception.</param>
        public SMPPSubmitMulti(string serviceType, TONType sourceAddrTON,
                                NPIType sourceAddrNPI, string sourceAddress,
                                byte numberOfDests, DestinationAddress[] destinationAddresses,
                                byte esmClass, byte protocolID,
                                PriorityType priorityFlag,
                                string scheduleDeliveryTime, string validityPeriod,
                                RegisteredDeliveryType registeredDelivery,
                                bool replaceIfPresentFlag, byte smDefaultMsgID,
                                DataCodingType dataCoding, object shortMessage)
            :
                base(protocolID, priorityFlag, scheduleDeliveryTime,
                      validityPeriod, replaceIfPresentFlag, smDefaultMsgID,
                      shortMessage, serviceType, esmClass, registeredDelivery,
                      sourceAddrTON, sourceAddrNPI, sourceAddress,
              dataCoding)
        {
            if (numberOfDests <= MAX_DESTS)
            {
                _NumberOfDests = numberOfDests;
            }
            else
            {
                throw new ArgumentException("NumberOfDests must be <= " +
                    MAX_DESTS + ".");
            }

            _DestAddresses = destinationAddresses;
            _CommandStatus = 0;
            _CommandID = CommandIDType.submit_multi;
        }

        ///<summary>
        /// Gets the hex encoding (big-endian) of this PDU.
        ///</summary>
        ///<return>The hex-encoded version of the PDU</return>
        public override byte[] GetMSBHexEncoding()
        {
            ArrayList pdu = GetPDUHeader();

            pdu.AddRange(ArrayCopyWithNull(
                System.Text.Encoding.ASCII.GetBytes(_ServiceType)));
            pdu.Add((byte)_SourceAddrTON);
            pdu.Add((byte)_SourceAddrNPI);
            pdu.AddRange(ArrayCopyWithNull(
                System.Text.Encoding.ASCII.GetBytes(_SourceAddress)));

            //number of destinations.
            pdu.Add(_NumberOfDests);
            //and their addresses
            foreach (DestinationAddress address in _DestAddresses)
            {
                pdu.AddRange(address.GetBytes());
            }

            pdu.AddRange(base.GetBytesAfterDestination());

            return EncodePDUForTransmission(pdu);
        }
    }
}

